#ifndef ITEM_DATA_H
#	define ITEM_DATA_H

#include <iostream>
#include <string>
#include <boost/pool/pool.hpp>
#include <boost/pool/object_pool.hpp>

#include "../../include/config.h"

// BDB 
#include <db_cxx.h>


using namespace std;

namespace HappyDB
{
namespace Common
{

#ifdef _WIN32_WINDOWS
	#pragma warning( disable : 4200 )
#endif


/**************************************************************************************************
 * 
 * For item struct
 *
 **************************************************************************************************/
typedef struct struct_item 
{
	u_int32_t	nbytes;				// size of data
	u_int32_t	nsuffix;			// length of flags-and-length string
	u_int32_t	nkey;				// key length, w/terminating null and padding
	void *		end[];
	// then null-terminated key
	// then "flags length \r\n" (no terminating null)
	// then data with terminating \r\n (no terminating null; it's binary !)

	// end[] data module
	// 
	//    | key | flags | data |
} ITEM;

inline void ITEM_set(ITEM * item, int nbytes, int  nsuffix, int nkey) 
{
	item->nbytes=nbytes;
	item->nsuffix = nsuffix;
	item->nkey = nkey;
}

#define ITEM_key(item) ((char*)&((item)->end[0]))

/* warning: don't use these macros with a function, as it evals its arg twice */
#define ITEM_suffix(item) ((char*) &((item)->end[0]) + (item)->nkey + 1)
#define ITEM_data(item) ((char*) &((item)->end[0]) + (item)->nkey + 1 + (item)->nsuffix)
#define ITEM_ntotal(item) (sizeof(struct struct_item) + (item)->nkey + 1 + (item)->nsuffix + (item)->nbytes)


/**************************************************************************************************
 * 
 * For Mempool 
 *
 **************************************************************************************************/
struct item_allocator_new_delete
{
  typedef std::size_t size_type;
  typedef std::ptrdiff_t difference_type;

  static char * malloc(const size_type bytes)
  {
	  return new (std::nothrow) char[bytes]; 
  }
  static void free(char * const block)
  { 
	  delete [] block; 
  }
};



/**************************************************************************************************
 * 
 * For BDB and BDB settings
 *
 **************************************************************************************************/

struct structBDBSettings {
    string db_file;    /* db filename, where dbfile located. */
    string env_home;    /* db env home dir path */
    int cache_size; /* cache size */
    int txn_lg_bsize; /* transaction log buffer size */
    int page_size;    /* underlying database pagesize*/
    DBTYPE db_type;
    int txn_nosync;    /* DB_TXN_NOSYNC flag, if 1 will lose transaction's durability for performance */
    int dldetect_val; /* do deadlock detect every *db_lock_detect_val* millisecond, 0 for disable */
    int chkpoint_val;  /* do checkpoint every *db_chkpoint_val* second, 0 for disable */
    int memp_trickle_val;  /* do memp_trickle every *memp_trickle_val* second, 0 for disable */
    int memp_trickle_percent; /* percent of the pages in the cache that should be clean.*/
    int db_flags; /* database open flags */
    int env_flags; /* env open flags */
	bool verbose;

    int is_replicated; /* replication is ON?? */

    string rep_localhost; /* local host in replication */
    int rep_localport;  /* local port in replication */
    string rep_remotehost; /* remote host in replication */
    int rep_remoteport;  /* remote port in replication */

    int rep_whoami;  /* replication role, MDB_MASTER/MDB_CLIENT/MDB_UNKNOWN */
    int rep_master_eid; /* replication master's eid */

    int rep_start_policy;
    int rep_nsites;

    int rep_ack_policy;

    int rep_ack_timeout;
    int rep_chkpoint_delay;
    int rep_conn_retry;
    int rep_elect_timeout;
    int rep_elect_retry;
    int rep_heartbeat_monitor; /* only available on a client */
    int rep_heartbeat_send;    /* only available on a master */
    int rep_lease_timeout;

    int rep_bulk;
	int rep_lease;  /* if master lease is enabled? */

    int rep_priority;

    int rep_req_max;
    int rep_req_min;

    int rep_fast_clock;
    int rep_slow_clock;

    int rep_limit_gbytes; 
    int rep_limit_bytes; 
};


enum enum_bdb_rep_role { BDB_MASTER, BDB_CLIENT, BDB_UNKNOWN };


static void bdb_err_callback(const DbEnv *, const char * errpfx, const char * msg){
	//time_t curr_time = time(NULL);
	//char time_str[32];
	//strftime(time_str, 32, "%c", localtime(&curr_time));
	//fprintf(stderr, "[%s] [%s] \"%s\"\n", errpfx, time_str, msg);
}

static void bdb_msg_callback(const DbEnv *dbenv, const char *msg){
	//time_t curr_time = time(NULL);
	//char time_str[32];
	//strftime(time_str, 32, "%c", localtime(&curr_time));
	//fprintf(stderr, "[%s] [%s] \"%s\"\n", PACKAGE, time_str, msg);
}

}
}


#endif
